﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Windows;
using MediaAssistant.Controls.Dialog;
using MediaAssistant.Data;
using MediaAssistant.Management;
using MefBasic;
using MediaAssistant.DAL;
using MediaAssistant.DAL.Constants;
using MefBasic.Threading;

namespace MediaAssistant.Controls.TagEditor
{
    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class TagEditorPresenter : APresenter<TagEditorView>, IDialogContentPresenter
    {
        [ImportingConstructor]
        public TagEditorPresenter(TagEditorView view)
            : base(view)
        {

        }

        [Import]
        public BackgroundScannerManager BackgroundScannerManager { get; set; }

        public DialogResult ShowDialog(IEnumerable<Music> musics)
        {
            BackgroundScannerManager.Pause();
            SetupInitialProperties(musics);
            var dialogResult = Resolve<IDialogPresenter>().ShowDialog("Edit Tags", this);
            if (dialogResult == DialogResult.Ok)
            {
                UpdateMusics(musics);
            }
            BackgroundScannerManager.Resume();
            return dialogResult;
        }

        private void UpdateMusics(IEnumerable<Music> musics)
        {
            DatabaseManager.Instance.TurnOffSaving = true;
            WaitScreenService.Show(musics.Count(),0);
            foreach (var music in musics)
            {
                var isChanger = false;
                if (IsEditTitleChecked)
                {
                    var newTitle = IsUseFilenameChecked ? Path.GetFileNameWithoutExtension(music.FileName) : Title;
                    music.Title = newTitle;
                    isChanger = true;
                }
                if (IsAlbumEditable)
                {
                    music.Album = Album;
                    isChanger = true;
                }

                if (IsArtistEditable)
                {
                    music.Artist = Artist;
                    isChanger = true;
                }

                if (IsComposerEditable)
                {
                    music.Composer = Composer;
                    isChanger = true;
                }

                if (IsGenreEditable)
                {
                    music.Genre = Genre;
                    isChanger = true;
                }
                if (isChanger)
                {
                    music.TagStatus = TagStatus.InvalidFile;
                }
                WaitScreenService.AdvanceProgress();
            }
            DatabaseManager.Instance.TurnOffSaving = false;
            WaitScreenService.Hide();
        }

        [Import]
        public WaitScreenService WaitScreenService { get; set; }

        private void UpdateMusicAction(Job obj)
        {
            var musicList = obj.Root.Store.GetObject<List<Music>>();
            foreach (var music in musicList)
            {
                DatabaseManager.Instance.UpdateAndLink(music);
                WaitScreenService.AdvanceProgress();
            }
        }

        private void SetupInitialProperties(IEnumerable<Music> musics)
        {
            Albums = DatabaseManager.Instance.GetKnownLibraryItems(LibraryItemType.Album).Select(o => o.Title).OrderBy(o => o);
            Artists = DatabaseManager.Instance.GetKnownLibraryItems(LibraryItemType.Artist).Select(o => o.Title).OrderBy(o => o);
            Composers = DatabaseManager.Instance.GetKnownLibraryItems(LibraryItemType.Composer).Select(o => o.Title).OrderBy(o => o);
            Genres = DatabaseManager.Instance.GetKnownLibraryItems(LibraryItemType.Genre).Select(o => o.Title).OrderBy(o => o);
            var selectedMusicAlbums = musics.Where(m => !string.IsNullOrWhiteSpace(m.Album)).Select(m => m.Album).Distinct();
            if (selectedMusicAlbums.Count() <= 1)
            {
                Album = selectedMusicAlbums.SingleOrDefault();
                IsAlbumEditable = true;
            }
            var selectedMusicArtists = musics.Where(m => !string.IsNullOrWhiteSpace(m.Artist)).Select(m => m.Artist).Distinct();
            if (selectedMusicArtists.Count() <= 1)
            {
                Artist = selectedMusicArtists.SingleOrDefault();
                IsArtistEditable = true;
            }
            var selectedMusicComposers = musics.Where(m => !string.IsNullOrWhiteSpace(m.Composer)).Select(m => m.Composer).Distinct();
            if (selectedMusicComposers.Count() <= 1)
            {
                Composer = selectedMusicComposers.SingleOrDefault();
                IsComposerEditable = true;
            }
            var selectedMusicGenres = musics.Where(m => !string.IsNullOrWhiteSpace(m.Genre)).Select(m => m.Genre).Distinct();
            if (selectedMusicGenres.Count() <= 1)
            {
                Genre = selectedMusicGenres.SingleOrDefault();
                IsGenreEditable = true;
            }
            var selectedTitles = musics.Where(m => !string.IsNullOrWhiteSpace(m.Title)).Select(m => m.Title).Distinct();
            if (selectedTitles.Count() <= 1)
            {
                Title = selectedTitles.SingleOrDefault();
                IsEditTitleChecked = true;
            }
        }

        public bool OnClosing(DialogResult dialogResult)
        {
            return true;
        }

        [Import]
        public LibraryDataSource DataSource { get; set; }

        public IEnumerable<string> Albums
        {
            get { return (IEnumerable<string>)GetValue(AlbumsProperty); }
            set { SetValue(AlbumsProperty, value); }
        }

        public static readonly DependencyProperty AlbumsProperty =
            DependencyProperty.Register("Albums", typeof(IEnumerable<string>), typeof(TagEditorPresenter), new UIPropertyMetadata(null));



        public string Album
        {
            get { return (string)GetValue(AlbumProperty); }
            set { SetValue(AlbumProperty, value); }
        }

        public static readonly DependencyProperty AlbumProperty =
            DependencyProperty.Register("Album", typeof(string), typeof(TagEditorPresenter), new UIPropertyMetadata(null));



        public bool IsAlbumEditable
        {
            get { return (bool)GetValue(IsAlbumEditableProperty); }
            set { SetValue(IsAlbumEditableProperty, value); }
        }

        public static readonly DependencyProperty IsAlbumEditableProperty =
            DependencyProperty.Register("IsAlbumEditable", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false));



        public bool IsArtistEditable
        {
            get { return (bool)GetValue(IsArtistEditableProperty); }
            set { SetValue(IsArtistEditableProperty, value); }
        }

        public static readonly DependencyProperty IsArtistEditableProperty =
            DependencyProperty.Register("IsArtistEditable", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false));



        public IEnumerable<string> Artists
        {
            get { return (IEnumerable<string>)GetValue(ArtistsProperty); }
            set { SetValue(ArtistsProperty, value); }
        }

        public static readonly DependencyProperty ArtistsProperty =
            DependencyProperty.Register("Artists", typeof(IEnumerable<string>), typeof(TagEditorPresenter), new UIPropertyMetadata(null));


        public string Artist
        {
            get { return (string)GetValue(ArtistProperty); }
            set { SetValue(ArtistProperty, value); }
        }

        public static readonly DependencyProperty ArtistProperty =
            DependencyProperty.Register("Artist", typeof(string), typeof(TagEditorPresenter), new UIPropertyMetadata(null));


        public IEnumerable<string> Composers
        {
            get { return (IEnumerable<string>)GetValue(ComposersProperty); }
            set { SetValue(ComposersProperty, value); }
        }

        public static readonly DependencyProperty ComposersProperty =
            DependencyProperty.Register("Composers", typeof(IEnumerable<string>), typeof(TagEditorPresenter), new UIPropertyMetadata(null));


        public string Composer
        {
            get { return (string)GetValue(ComposerProperty); }
            set { SetValue(ComposerProperty, value); }
        }

        public static readonly DependencyProperty ComposerProperty =
            DependencyProperty.Register("Composer", typeof(string), typeof(TagEditorPresenter), new UIPropertyMetadata(null));


        public bool IsComposerEditable
        {
            get { return (bool)GetValue(IsComposerEditableProperty); }
            set { SetValue(IsComposerEditableProperty, value); }
        }

        public static readonly DependencyProperty IsComposerEditableProperty =
            DependencyProperty.Register("IsComposerEditable", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false));


        public IEnumerable<string> Genres
        {
            get { return (IEnumerable<string>)GetValue(GenresProperty); }
            set { SetValue(GenresProperty, value); }
        }

        public static readonly DependencyProperty GenresProperty =
            DependencyProperty.Register("Genres", typeof(IEnumerable<string>), typeof(TagEditorPresenter), new UIPropertyMetadata(null));


        public string Genre
        {
            get { return (string)GetValue(GenreProperty); }
            set { SetValue(GenreProperty, value); }
        }

        public static readonly DependencyProperty GenreProperty =
            DependencyProperty.Register("Genre", typeof(string), typeof(TagEditorPresenter), new UIPropertyMetadata(null));



        public bool IsGenreEditable
        {
            get { return (bool)GetValue(IsGenreEditableProperty); }
            set { SetValue(IsGenreEditableProperty, value); }
        }

        public static readonly DependencyProperty IsGenreEditableProperty =
            DependencyProperty.Register("IsGenreEditable", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false, OnPropertyChanged));

        protected override void DoPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            switch (e.Property.Name)
            {
                case "IsEditTitleChecked":
                    IsTitleEditable = IsUseFilenameChecked == false && IsEditTitleChecked;
                    break;
                case "IsUseFilenameChecked":
                    if (IsUseFilenameChecked)
                        IsEditTitleChecked = true;
                    IsTitleEditable = IsUseFilenameChecked == false && IsEditTitleChecked;
                    break;
            }
        }

        public bool IsEditTitleChecked
        {
            get { return (bool)GetValue(IsEditTitleCheckedProperty); }
            set { SetValue(IsEditTitleCheckedProperty, value); }
        }

        public static readonly DependencyProperty IsEditTitleCheckedProperty =
            DependencyProperty.Register("IsEditTitleChecked", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false, OnPropertyChanged));



        public bool IsUseFilenameChecked
        {
            get { return (bool)GetValue(IsUseFilenameCheckedProperty); }
            set { SetValue(IsUseFilenameCheckedProperty, value); }
        }

        public static readonly DependencyProperty IsUseFilenameCheckedProperty =
            DependencyProperty.Register("IsUseFilenameChecked", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false, OnPropertyChanged));

        public bool IsTitleEditable
        {
            get { return (bool)GetValue(IsTitleEditableProperty); }
            set { SetValue(IsTitleEditableProperty, value); }
        }

        public static readonly DependencyProperty IsTitleEditableProperty =
            DependencyProperty.Register("IsTitleEditable", typeof(bool), typeof(TagEditorPresenter), new UIPropertyMetadata(false));



        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(TagEditorPresenter), new UIPropertyMetadata(null));

    }
}
